﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include "ExprEngine.h"

#include <string>
#include <sstream>
#include <iomanip>
#include <time.h>

#include "GbmpNew.h"
#include "TransferOwnership.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace std;
using namespace gcmp;

const wchar_t* TR_MODULE_NAME = L"ExprEngine";

namespace gcmp
{
    const double M_PI = 3.14159265358979323846;
    const int PARSE_POOL_SIZE = 100;
}

// 一些内置自定义函数

/// \brief StrLength（函数）
class StrLengthFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"StrLength";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool StrLengthFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1 && params->GetParam(0)->GetType() == ExprDataType::String)
    {
        pResultData->SetAsInteger(static_cast<long>(wcslen(params->GetParam(0)->GetAsString())));
        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);
        return true;
    }
    else
        return false;
}

/// \brief StrToInt(函数)
class StrToIntFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"StrtoInt";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool StrToIntFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1 && params->GetParam(0)->GetType() == ExprDataType::String)
    {
        pResultData->SetAsInteger(_wtoi(params->GetParam(0)->GetAsString()));
        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);
        return true;
    }
    else
        return false;
}

/// \brief cos（函数）
class CCosFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"cos";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CCosFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Angle
            && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num)
            return false;
        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);

        double dangle = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dangle = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dangle = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        dangle = (dangle / 180) * M_PI;

        pResultData->SetAsFloat(cos(dangle));

        return true;
    }

    return false;
}


/// \brief sin（函数）
class CSinFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"sin";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CSinFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Angle && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num)
            return false;
        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);

        double dangle = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dangle = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dangle = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        dangle = (dangle / 180) * M_PI;

        pResultData->SetAsFloat(sin(dangle));

        return true;
    }

    return false;
}


/// \brief tan（函数）
class CTanFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"tan";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};
bool CTanFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Angle && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num)
            return false;
        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);

        double dangle = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dangle = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dangle = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        dangle = (dangle / 180) * M_PI;

        pResultData->SetAsFloat(tan(dangle));

        return true;
    }
    return false;
}


/// \brief arcsin（函数）
class CArcSinFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"asin";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CArcSinFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num
            && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Double)
            return false;
        UnitMap type(ExprUnitType::Angle);
        pResultData->SetUnitType(type);

        double dVal = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dVal = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dVal = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        double dangle = asin(dVal);
        dangle = (dangle / M_PI) * 180.0;

        pResultData->SetAsFloat(dangle);

        return true;
    }

    return false;
}

/// \brief acos（函数）
class CArcCosFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"acos";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CArcCosFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num
            && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Double)
            return false;
        UnitMap type(ExprUnitType::Angle);
        pResultData->SetUnitType(type);

        double dVal = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dVal = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dVal = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        double dangle = acos(dVal);
        dangle = (dangle / M_PI) * 180.0;

        pResultData->SetAsFloat(dangle);

        return true;
    }

    return false;
}


/// \brief atan（函数）
class CArcTanFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"atan";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CArcTanFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        if (params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Num
            && params->GetParam(0)->GetUnitType().GetSingleUnit() != ExprUnitType::Double)
            return false;
        UnitMap type(ExprUnitType::Angle);
        pResultData->SetUnitType(type);

        double dVal = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dVal = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dVal = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        double dangle = atan(dVal);
        dangle = (dangle / M_PI) * 180.0;

        pResultData->SetAsFloat(dangle);

        return true;
    }

    return false;
}

/// \brief sqrt（函数）
class CSqrtFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"sqrt";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CSqrtFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 处理单位
        UnitMap type(params->GetParam(0)->GetUnitType());
        type.Pow(1.0 / 2.0);
        pResultData->SetUnitType(type);

        double dVal = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dVal = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dVal = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        pResultData->SetAsFloat(sqrt(dVal));

        return true;
    }

    return false;
}

/// \brief pow（函数）
class CPowFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"pow";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Float;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CPowFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 2)
    {
        double dVal = 0.0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            dVal = params->GetParam(0)->GetAsFloat();
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            dVal = static_cast<double>(params->GetParam(0)->GetAsInteger());
        }
        else
        {
            return false;
        }

        double dVal1 = 0.0;
        if (params->GetParam(1)->GetType() == ExprDataType::Float)
        {
            dVal1 = params->GetParam(1)->GetAsFloat();
        }
        else if (params->GetParam(1)->GetType() == ExprDataType::Integer)
        {
            dVal1 = static_cast<double>(params->GetParam(1)->GetAsInteger());
        }
        else
        {
            return false;
        }
        // 处理单位
        if (params->GetParam(1)->GetUnitType().GetSingleUnit() != ExprUnitType::Num
            && params->GetParam(1)->GetUnitType().GetSingleUnit() != ExprUnitType::Int
            && params->GetParam(1)->GetUnitType().GetSingleUnit() != ExprUnitType::Double)
            return false;
        UnitMap type(params->GetParam(0)->GetUnitType());
        type.Pow(dVal1);
        pResultData->SetUnitType(type);

        pResultData->SetAsFloat(pow(dVal, dVal1));

        return true;
    }

    return false;
}

/// \brief if（函数）
class CIfFunction : public IExprCustomFunction
{
public:
    CIfFunction() :m_exprDataType(ExprDataType::Float) {}
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"if";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return m_exprDataType;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);

private:
    ExprDataType m_exprDataType;
};

bool CIfFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 3)
    {
        bool bCondition = false;
        if (params->GetParam(0)->GetType() == ExprDataType::Boolean)
        {
            bCondition = params->GetParam(0)->GetAsBoolean();
        }
        else
        {
            return false;
        }

        if ((params->GetParam(1)->GetType() == ExprDataType::Boolean) && (params->GetParam(2)->GetType() == ExprDataType::Boolean))
        {
            m_exprDataType = ExprDataType::Boolean;
        }
        else if ((params->GetParam(1)->GetType() == ExprDataType::String))
        {
            if ((params->GetParam(2)->GetType() == ExprDataType::String))
            {
                m_exprDataType = ExprDataType::String;
            }
            else
            {
                // 仅Param1是字符串，不允许
                return false;
            }
        }
        else if ((params->GetParam(2)->GetType() == ExprDataType::String))
        {
            // 仅Param2是字符串，不允许
            return false;
        }
        else
        {
            m_exprDataType = ExprDataType::Float;
        }

        // 分析单位
        if (bCondition)
        {
            UnitMap oUnitMap = params->GetParam(1)->GetUnitType();
            pResultData->SetUnitType(oUnitMap);
        }
        else
        {
            UnitMap oUnitMap = params->GetParam(2)->GetUnitType();
            pResultData->SetUnitType(oUnitMap);
        }

        double dVal1 = 0.0;
        const wchar_t* strVal1 = nullptr;
        if (params->GetParam(1)->GetType() == ExprDataType::Float)
        {
            dVal1 = params->GetParam(1)->GetAsFloat();
        }
        else if (params->GetParam(1)->GetType() == ExprDataType::Integer)
        {
            dVal1 = static_cast<double>(params->GetParam(1)->GetAsInteger());
        }
        else if (params->GetParam(1)->GetType() == ExprDataType::Boolean)
        {
            dVal1 = static_cast<double>(params->GetParam(1)->GetAsBoolean());
        }
        else if (params->GetParam(1)->GetType() == ExprDataType::String)
        {
            strVal1 = params->GetParam(1)->GetAsString();
        }
        else
        {
            return false;
        }

        double dVal2 = 0.0;
        const wchar_t* strVal2 = nullptr;
        if (params->GetParam(2)->GetType() == ExprDataType::Float)
        {
            dVal2 = params->GetParam(2)->GetAsFloat();
        }
        else if (params->GetParam(2)->GetType() == ExprDataType::Integer)
        {
            dVal2 = static_cast<double>(params->GetParam(2)->GetAsInteger());
        }
        else if (params->GetParam(2)->GetType() == ExprDataType::Boolean)
        {
            dVal2 = static_cast<double>(params->GetParam(2)->GetAsBoolean());
        }
        else if (params->GetParam(2)->GetType() == ExprDataType::String)
        {
            strVal2 = params->GetParam(2)->GetAsString();
        }
        else
        {
            return false;
        }

        if (m_exprDataType == ExprDataType::Boolean)
        {
            pResultData->SetAsBoolean(bCondition ? params->GetParam(1)->GetAsBoolean() : params->GetParam(2)->GetAsBoolean());
        }
        else if (m_exprDataType == ExprDataType::String)
        {
            pResultData->SetAsString(bCondition ? strVal1 : strVal2);
        }
        else
        {
            pResultData->SetAsFloat(bCondition ? dVal1 : dVal2);
        }

        return true;
    }

    return false;
}

/// \brief 向下取整
class CRoundDownFunction : public IExprCustomFunction
{
public:

    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"rounddown";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CRoundDownFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 设置单位和参数的单位一致
        UnitMap oUnitMap = params->GetParam(0)->GetUnitType();
        pResultData->SetUnitType(oUnitMap);

        // 获取参数值，支持float和int两种
        int resultValue = 0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            double val = params->GetParam(0)->GetAsFloat();
            resultValue = static_cast<int>(floor(val));
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            resultValue = params->GetParam(0)->GetAsInteger();
        }
        else
        {
            return false;
        }
        pResultData->SetAsInteger(resultValue);

        return true;
    }

    return false;
}

/// \brief 向上取整
class CRoundUpFunction : public IExprCustomFunction
{
public:

    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"roundup";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CRoundUpFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 设置单位和参数的单位一致
        UnitMap oUnitMap = params->GetParam(0)->GetUnitType();
        pResultData->SetUnitType(oUnitMap);

        // 获取参数值，支持float和int两种
        int resultValue = 0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            double val = params->GetParam(0)->GetAsFloat();
            resultValue = static_cast<int>(ceil(val));
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            resultValue = params->GetParam(0)->GetAsInteger();
        }
        else
        {
            return false;
        }
        pResultData->SetAsInteger(resultValue);

        return true;
    }

    return false;
}

/// \brief 四舍五入取整
class CRoundFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"round";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr);
};

bool CRoundFunction::DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag)
{
    if (params->Count() == 1)
    {
        // 设置单位和参数的单位一致
        UnitMap oUnitMap = params->GetParam(0)->GetUnitType();
        pResultData->SetUnitType(oUnitMap);

        // 获取参数值，支持float和int两种
        int resultValue = 0;
        if (params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            double val = params->GetParam(0)->GetAsFloat();
            resultValue = static_cast<int>(round(val));
        }
        else if (params->GetParam(0)->GetType() == ExprDataType::Integer)
        {
            resultValue = params->GetParam(0)->GetAsInteger();
        }
        else
        {
            return false;
        }
        pResultData->SetAsInteger(resultValue);

        return true;
    }

    return false;
}


/// \brief 获得当前系统时间，参数_Tm为返回值
namespace
{
    void GetCurrentTime(struct tm* _Tm)
    {
        time_t time_seconds = time(nullptr);
        // localtime函数返回的指针是一个静态内存，不需要释放，但是不是线程安全的，Windows平台下可以用localtime_s代替，Linux平台下可以用localtime_r代替
#ifdef _WINDOWS
        localtime_s(_Tm, &time_seconds);
#else
        localtime_r(&time_seconds, _Tm);
#endif
    }
}

/// \brief 获得当前系统时间的小时（函数）
class CTimeHourFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"TimeHour";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr)
    {
        struct tm now_time;
        GetCurrentTime(&now_time);
        pResultData->SetAsInteger(now_time.tm_hour);

        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);
        return true;
    }
};

/// \brief 获得当前系统时间的分钟（函数）
class CTimeMinuteFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"TimeMinute";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr)
    {
        struct tm now_time;
        GetCurrentTime(&now_time);
        pResultData->SetAsInteger(now_time.tm_min);

        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);
        return true;
    }
};

/// \brief 获得当前系统时间的秒钟（函数）
class CTimeSecondFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"TimeSecond";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::Integer;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr)
    {
        struct tm now_time;
        GetCurrentTime(&now_time);
        pResultData->SetAsInteger(now_time.tm_sec);

        UnitMap type(ExprUnitType::Num);
        pResultData->SetUnitType(type);
        return true;
    }
};

/// \brief 将长度类型参数转换为字符串参数类型（函数）
class ToStringFunction : public IExprCustomFunction
{
public:
    /// \brief 获取函数名称
    ///
    /// \return 函数名称
    const wchar_t* GetFunctionName()
    {
        return L"ToString";
    }

    /// \brief 获取函数返回值类型
    ///
    /// \return 返回值类型
    ExprDataType GetResultDataType()
    {
        return ExprDataType::String;
    }

    bool DoExectute(FunctionParams* params, ExprNodeData* pResultData, void* pTag = nullptr)
    {
        if (params->Count() == 2 && params->GetParam(0)->GetType() == ExprDataType::Float)
        {
            if (params->GetParam(1)->GetAsInteger() < 0)
            {
                return false;
            }
            std::wostringstream woss;
            woss << std::fixed << std::setprecision(params->GetParam(1)->GetAsInteger()) << params->GetParam(0)->GetAsFloat();
            pResultData->SetAsString(woss.str().c_str());
            UnitMap type(ExprUnitType::Length);
            pResultData->SetUnitType(type);
            return true;
        }
        else
            return false;
    }
};

static StrLengthFunction s_strLengthfunction;
static StrToIntFunction s_strToIntFunction;
static CCosFunction     s_cosFunction;
static CSinFunction     s_sinFunction;
static CTanFunction     s_tanFunction;
static CArcSinFunction     s_asinFunction;
static CArcCosFunction     s_acosFunction;
static CArcTanFunction     s_atanFunction;
static CSqrtFunction     s_sqrtFunction;
static CPowFunction     s_powFunction;
static CIfFunction     s_ifFunction;
static CRoundUpFunction s_roundupFunction;
static CRoundDownFunction s_rounddownFunction;
static CRoundFunction s_roundFunction;
static CTimeHourFunction     s_timeHourFunction;
static CTimeMinuteFunction     s_timeMinuteFunction;
static CTimeSecondFunction     s_timeSecondFunction;
static ToStringFunction s_toStringFunction;

/// \brief ExprCustomParser的实现
bool ExprCustomEngine::FuncNameCmp::operator () (const std::wstring& name1, const std::wstring& name2) const
{
    // 都转化为小写字符进行比较
    std::wstring lowerStr1 = name1;
    std::transform(name1.begin(), name1.end(), lowerStr1.begin(), ::tolower);

    std::wstring lowerStr2 = name2;
    std::transform(name2.begin(), name2.end(), lowerStr2.begin(), ::tolower);

    return lowerStr1 < lowerStr2;
}

ExprCustomEngine::ExprCustomEngine()
{
    Init();
}

ExprCustomEngine::~ExprCustomEngine()
{
    m_pExprPaserContainer.clear();
}

gcmp::OwnerPtr<IExprParser> ExprCustomEngine::CreateParser()
{
    return TransferOwnership(NEW_AS_OWNER_PTR(ExprCustomParser, this));
}

void ExprCustomEngine::Init()
{
    m_pDataProvider = nullptr;
    RegisterFunction(&s_strLengthfunction);
    RegisterFunction(&s_strToIntFunction);
    RegisterFunction(&s_cosFunction);
    RegisterFunction(&s_sinFunction);
    RegisterFunction(&s_tanFunction);
    RegisterFunction(&s_acosFunction);
    RegisterFunction(&s_asinFunction);
    RegisterFunction(&s_atanFunction);
    RegisterFunction(&s_sqrtFunction);
    RegisterFunction(&s_powFunction);
    RegisterFunction(&s_ifFunction);
    RegisterFunction(&s_roundupFunction);
    RegisterFunction(&s_rounddownFunction);
    RegisterFunction(&s_roundFunction);
    RegisterFunction(&s_timeHourFunction);
    RegisterFunction(&s_timeMinuteFunction);
    RegisterFunction(&s_timeSecondFunction);
    RegisterFunction(&s_toStringFunction);
}

void ExprCustomEngine::SetNodeDataProvider(gcmp::OwnerPtr<IExprNodeDataProvider> pDataProvider)
{
    m_pDataProvider = TransferOwnership(pDataProvider);
}

IExprNodeDataProvider* ExprCustomEngine::GetNodeDataProvider()
{
    return m_pDataProvider.get();
}

bool ExprCustomEngine::RegisterExprParser(const wchar_t* pExprParserName, gcmp::OwnerPtr<IExprParser> pNewExprParser)
{
    if (pNewExprParser == nullptr)
    {
        return false;
    }

    IExprParser* pPaser = FindParser(pExprParserName);
    if (pPaser != nullptr)
    {
        UnRegisterExprParser(pExprParserName);
    }

    m_pExprPaserContainer[pExprParserName] = TransferOwnership(pNewExprParser);

    return true;
}

bool ExprCustomEngine::UnRegisterExprParser(const wchar_t* pExprParserName)
{
    std::map<std::wstring, gcmp::OwnerPtr<IExprParser> >::iterator iter = m_pExprPaserContainer.find(pExprParserName);
    if (iter == m_pExprPaserContainer.end())
    {
        return false;
    }

    m_pExprPaserContainer.erase(pExprParserName);

    return true;
}

IExprParser* ExprCustomEngine::FindParser(const wchar_t* pExprParserName)
{
    std::map<std::wstring, gcmp::OwnerPtr<IExprParser> >::iterator iter = m_pExprPaserContainer.find(pExprParserName);
    return (iter != m_pExprPaserContainer.end()) ? (iter->second.get()) : nullptr;
}

void ExprCustomEngine::RegisterFunction(IExprCustomFunction* pFunction)
{
    std::pair<std::wstring, IExprCustomFunction*> function;
    function.first = pFunction->GetFunctionName();
    function.second = pFunction;
    m_pFunctionContainer.insert(function);
}

void ExprCustomEngine::UnRegisterFunction(IExprCustomFunction* pFunction)
{
    m_pFunctionContainer.erase(pFunction->GetFunctionName());
}

IExprCustomFunction* ExprCustomEngine::FindFunction(const wchar_t* aName)
{
    auto iter = m_pFunctionContainer.find(aName);
    if (iter != m_pFunctionContainer.end())
        return iter->second;
    else
        return nullptr;
}

IExprCustomFunction* ExprCustomEngine::FindFunctionAndAdjustName(wchar_t* aName)
{
    auto iter = m_pFunctionContainer.find(aName);
    if (iter != m_pFunctionContainer.end())
    {
        wcscpy(aName, iter->first.c_str());
        return iter->second;
    }

    return nullptr;
}

// 导出函数实现
namespace gcmp
{
    gcmp::OwnerPtr<IExprEngine> CreateEngine()
    {
        return TransferOwnership(NEW_AS_OWNER_PTR(ExprCustomEngine));
    }
}
